package org.rfs.ipodencoder;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import com.trolltech.qt.QThread;

public class QExecuteTaskEx implements Runnable {
	private Process proc;
	private QOutputParser outputParser;
	private ArrayList<FFMpegEncodeOptions> encodeOptions;
	
	public QExecuteTaskEx(QOutputParser outputParser) {
		this.outputParser = outputParser;
	}
	
	public void run() {
		for (FFMpegEncodeOptions ffmeo : encodeOptions) {
		if (System.getProperty("os.name").startsWith("Windows")) {
				execWindows(ffmeo);
			} else if (System.getProperty("os.name").startsWith("Mac")) {
				execMac(ffmeo);
			} else {
				System.err.println("unsupported OS..."
						+ System.getProperty("os.name"));
				return;
			}
		}
//		} else {
//			System.err.println("no exec command specified...exiting");
//		}
	}
	
    public boolean execWindows(FFMpegEncodeOptions ffmeo) {
        StringTokenizer st = new StringTokenizer(ffmeo.encodecommand, " ");
        ArrayList<String> execList = new ArrayList<String>(Arrays.asList("cmd.exe","/C"));
        while (st.hasMoreTokens())
        {
            execList.add(st.nextToken());
        }

        return mainExec(ffmeo, execList);
    }

    public boolean execMac(FFMpegEncodeOptions ffmeo) {
        StringTokenizer st = new StringTokenizer(ffmeo.encodecommand, " ");
        //ArrayList<String> execList = new ArrayList<String>(Arrays.asList("/bin/sh","-c"));
        ArrayList<String> execList = new ArrayList<String>();
        while (st.hasMoreTokens())
        {
            execList.add(st.nextToken());
        }

        return mainExec(ffmeo, execList);
    }
    
    private ArrayList<String> replaceInArrayList(ArrayList<String> aList, String source, String dest) {
    	ArrayList<String> tmp = new ArrayList<String>(aList);
    	for (int i=0; i<tmp.size(); ++i) {
    		if (tmp.get(i).toUpperCase().equals(source.toUpperCase())) {
    			tmp.set(i, dest);
    		}		
    	}
    	return tmp;
    }
	
	private boolean mainExec(FFMpegEncodeOptions ffmeo, ArrayList<String> execCommand) {
		System.out.println("DEBUG: " + ffmeo.encodecommand);
        ArrayList<String> executeCommand = null;
        String inputFile, outputFile;
        
        //should never happen... let's see. (TODO: verify)
//        if (lInputFiles.size() != lOutputFiles.size()) {
//        	System.err.println("severe error in QExecuteTaskEx - lInputFiles.size() != lOutputFiles");
//        	return false;
//        }
        
    	inputFile = ffmeo.inputfilename;
    	outputFile = ffmeo.outputfilename;
    	
        executeCommand = new ArrayList<String>(replaceInArrayList(execCommand, "@INPUTFILE@", inputFile));
		executeCommand = new ArrayList<String>(replaceInArrayList(executeCommand, "@OUTPUTFILE@", outputFile));
        
		ProcessBuilder builder;
        try {
            builder = new ProcessBuilder(executeCommand);
            builder.directory(new File("bin"));
            builder.redirectErrorStream(true);

            proc = builder.start();
            
            outputParser.setOutputReader(new BufferedReader(new InputStreamReader(proc.getInputStream())));
            outputParser.setInputWriter(new PrintWriter(proc.getOutputStream()));
            outputParser.setFileName(inputFile);
            outputParser.setPass(ffmeo.encodemode);
            QThread qExec = new QThread(outputParser);
//            qExec.finished.connect(outputParser, "encodingFinished()");
            qExec.start();
            //replace previous 2 lines with "outputParser.start()" to get rid of Qt if needed 
            
            int nResult = proc.waitFor();
            qExec.join(); //wait for the other one too...

            if (nResult == 0) {
                return true;
            } else
            	return false;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

	public void setEncodingOptions(ArrayList<FFMpegEncodeOptions> encodeOptions) {
		this.encodeOptions = encodeOptions;
	}
}
